﻿using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace GameFrameWork
{
    [DisallowMultipleComponent]
    public sealed class UIReuseItem : UIBehaviour, IUIGetter, IPointerClickHandler
    {
        [SerializeField] bool _selectable;
        List<UIReuseList> _nestReuseLists;

        public RectTransform RectTransform { get; private set; }
        public Action OnSelect { get; set; }

        protected override void Awake()
        {
            base.Awake();

            RectTransform = GetComponent<RectTransform>();
            if (_selectable) gameObject.AddComponent<UIEmptyRaycast>();
        }

        public List<UIReuseList> GetNestReuseList()
        {
            if (_nestReuseLists == null)
            {
                _nestReuseLists = new List<UIReuseList>();
                foreach (var obj in _variables)
                {
                    if (obj.TryGetComponent<UIReuseList>(out var reuseList))
                        _nestReuseLists.Add(reuseList);
                }
            }
            return _nestReuseLists;
        }

        [SerializeField] List<GameObject> _variables = new List<GameObject>();

#if UNITY_EDITOR
        public List<GameObject> Variables { get => _variables; set => _variables = value; }
#endif

        T IUIGetter.GetComponent<T>(int idx)
        {
            Assert.IsTrue(idx >= 0 && idx < _variables.Count, $"控件下标超出范围(可能是UIReuseItem预制和UIReuseItemCtrl没对应上), idx: {idx}, range: [0, {(_variables.Count == 0 ? 0 : _variables.Count - 1)}]");
            var go = _variables[idx];
            if (!go.TryGetComponent<T>(out var component))
            {
                Debug.LogError($"UIReuseItem 预制上GO {go.name} 找不到UI控件 {typeof(T).Name}, index: {idx}");
                return default;
            }
            return component;
        }

        GameObject IUIGetter.GetGameObject(int idx)
        {
            Assert.IsTrue(idx >= 0 && idx < _variables.Count, $"控件下标超出范围(可能是UIReuseItem预制和UIReuseItemCtrl没对应上), idx: {idx}, range: [0, {(_variables.Count == 0 ? 0 : _variables.Count - 1)}]");
            return _variables[idx];
        }


        void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
        {
            var handlers = GetComponentsInChildren<IPointerClickHandler>();
            foreach (var handler in handlers)
            {
                if (handler == this as IPointerClickHandler) continue;

                if (handler is UIBehaviour behaviour)
                {
                    if (!behaviour.enabled || !behaviour.gameObject.activeInHierarchy)
                        continue;

                    var rectTransform = behaviour.GetComponent<RectTransform>();
                    if (RectTransformUtility.RectangleContainsScreenPoint(rectTransform, eventData.position, eventData.enterEventCamera))
                    {
                        if (behaviour is UIReuseItem reuseItem)
                        {
                            if (!reuseItem._selectable) continue;

                            ExecuteEvents.Execute(reuseItem.gameObject, eventData, ExecuteEvents.pointerClickHandler);
                            return;
                        }
                        else
                        {
                            handler.OnPointerClick(eventData);
                            return;
                        }
                    }
                }
            }
            if (!_selectable) return;

            OnSelect?.Invoke();
        }


        public void Layout(bool immediately = false)
        {
            if (immediately)
                LayoutRebuilder.ForceRebuildLayoutImmediate(RectTransform);
            else
                LayoutRebuilder.MarkLayoutForRebuild(RectTransform);
        }
    }


    public interface IUIGetter
    {
        T GetComponent<T>(int idx) where T : Component;
        GameObject GetGameObject(int idx);
    }
}

